/*
 * Matrix: 
 * 
 * [ a c e ]
 * [ b d f ]
 * 
 * tx,ty: translation 
 * sx,sy: scaling
 *  
 * [sx 00 tx]
 * [00 sy ty]
 * [00 00 01]
 * 
 * Scale
 * 
 * [ cos(a) -sin(a)  0 ]
 * [ sin(a)  cos(a)  0 ]
 * [   0       0     1 ]
 *  // or while rotating the coordinate system axes by angle a. 
 * [  cos(a) sin(a)  0 ] 
 * [ -sin(a) cos(a)  0 ]
 * [   0       0     1 ]
 * 
 */
fi.foyt.svg.svgdom.FNISVGPathElementController = Class.create(fi.foyt.svg.svgdom.FNISVGElementController, {
  initialize: function($super){
    this.pathParser = new fi.foyt.svg.svgdom.FNISVGPathParser();
  },
  getPathSegmentsObject: function(element){
    if (element.segments == null)
      element.segments = this.pathParser.parsePath(element);
    
    return element.segments;
  },
  appendSegment: function(element, segment){
    this.getPathSegmentsObject(element).push(segment);
    this.markPathChanged(element);
  },
  getSegments: function(element){
    return this.getPathSegmentsObject(element);
  },
  markPathChanged: function (element) {
    element.pathChanged = true;
  },
  updatePath: function(element){
    if ((element.segments != null) && (element.pathChanged == true)) {
      if (element.segments.length > 0) {
    var d = element.segments[0].toString();
    for (var i = 1; i < element.segments.length; i++) 
      d += ' ' + element.segments[i].toString();
    element.setAttributeNS(null, 'd', d);
    }
      element.pathChanged = false;
    }
  },
  reparsePath: function (element) {
    element.segments = this.pathParser.parsePath(element);
    this.markPathChanged(element);
  },
  moveBy: function(element, x, y) {
    try {
    var segments = this.getSegments(element);
    
    for (var i = 0; i < segments.length; i++) {
      var segment = segments[i];
      var parameters = segment.getParameters(); 
      for (var j = 0; j < parameters.length; j++) {
        var parameter = parameters[j];
        parameter.x += x;
        parameter.y += y; 
      }
    }
    element.pathChanged = true;
    
    this.updatePath(element);
  } catch (e) {
    throw new Error("FNISVGPathElementController::moveBy: " + e);
  }
  },
  moveTo: function(element, x, y){
    try {
    var bbox = element.getBBox();
      this.moveBy(element, x - bbox.x, y - bbox.y);
  } catch (e) {
    throw new Error("FNISVGPathElementController::moveTo: " + e);
  }
  },
  resizeTo: function (element, width, height) {
  try {
      var elementBo = element.getBBox();
    if ((elementBo.width > 0) && (elementBo.height > 0)) {
    var scaleX = width / elementBo.width;
    var scaleY = height / elementBo.height;   
    this.resizeBy(element, scaleX, scaleY);
    } 
  } catch (e) {
    throw new Error("FNISVGPathElementController::resizeTo: " + e);
  }
  },
  resizeBy: function (element, scaleX, scaleY) {
    try {
    var elementBo = element.getBBox();  
      var xTrans = (elementBo.x * scaleX) - elementBo.x;
      var yTrans = (elementBo.y * scaleY) - elementBo.y;    
      var segments = this.getSegments(element);
    
    for (var i = 0; i < segments.length; i++) {
        var segment = segments[i]; 
        var parameters = segment.getParameters(); 
        for (var j = 0; j < parameters.length; j++) {
          var parameter = parameters[j];
          parameter.x = (parameter.x * scaleX) - xTrans;
          parameter.y = (parameter.y * scaleY) - yTrans; 
        }
      }
    
    element.pathChanged = true;  
    this.updatePath(element);
  } catch (e) {
    throw new Error("FNISVGPathElementController::resizeBy: " + e);
  }
  },
  rotateBy: function (element, angle, originX, originY) {
    try {
    var sAngle = Math.sin(angle);
      var cAngle = Math.cos(angle);
    
      var segments = this.getSegments(element);
      for (var i = 0; i < segments.length; i++) {
        var segment = segments[i]; 
        var parameters = segment.getParameters(); 
        for (var j = 0; j < parameters.length; j++) {
          var parameter = parameters[j];      
          var x = parseFloat(parameter.x);
          var y = parseFloat(parameter.y);
      
          parameter.x = originX + cAngle * (x - originX) - sAngle * (y - originY);
          parameter.y = originY + sAngle * (x - originX) + cAngle *  (y - originY);
        }
      }
  
    element.pathChanged = true;  
    this.updatePath(element);
  } catch (e) {
    throw new Error("FNISVGPathElementController::rotateBy: " + e);
  }
  },
  supports: function (operation) {
    return ((operation == fi.foyt.svg.svgdom.FNISVGElementController.OPERATION_MOVE)||(operation == fi.foyt.svg.svgdom.FNISVGElementController.OPERATION_RESIZE)||(operation == fi.foyt.svg.svgdom.FNISVGElementController.OPERATION_ROTATE));
  }
});